package com.nettest.service.system;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang.math.NumberUtils;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.nettest.dao.system.RoleDao;
import com.nettest.entity.BaseEntity;
import com.nettest.entity.system.Menu;
import com.nettest.entity.system.Role;
import com.nettest.service.event.RoleChangedEvent;
import com.nettest.util.StringUtils;

@Service
@Transactional
public class RoleService implements ApplicationContextAware{
	@Autowired
	private RoleDao roleDao;
	private ApplicationContext applicationContext;
	
	public BaseEntity save(BaseEntity entity) throws Exception {
		return roleDao.save((Role)entity);
	}

	public void delete(Long id) throws Exception {
		roleDao.delete(id);
	}

	public Role get(Serializable id) throws Exception {
		return roleDao.get(id);
	}
	
	public Role get(String roleId) throws Exception {
		List<Role> list = roleDao.findBySql("select r from Role r where r.roleId = ?",roleId);
		Role r = null;
		if(list != null && !list.isEmpty()) {
			r = list.get(0);
		}
		return r;
	}
	
	public List<Role> queryAllRole() {
		List<Role> list = roleDao.findBySql("select r from Role r ");
		return list;
	}

	public Role queryRoleById(String roleId) throws Exception {
		return get(roleId);
	}

	public void insertRole(Role role) {
		String parentId = role.getParentId();
		if (parentId != null) {
			String newRoleId = null;
			String maxRoleId = queryMaxRoleId(parentId);
			if (StringUtils.isEmpty(maxRoleId)) {
				newRoleId = "0".equals(parentId) ? "001" : (parentId + "001");
			}
			else {
				newRoleId = "00" + String.valueOf(NumberUtils.toLong(maxRoleId) + 1);
			}
			role.setRoleId(newRoleId);
			roleDao.save(role);
		}
	}

	public String queryMaxRoleId(String parentId) {		
		return roleDao.queryMaxRoleId(parentId);
	}

	public void updateRole(Role role) throws Exception {
		Role role2 = queryRoleById(role.getRoleId());
		if(role2 == null) throw new Exception("Role name: " + role.getRoleName() + " has been deleted");
		role2.setRoleName(role.getRoleName());
		role2.setMemo(role.getMemo());
		roleDao.save(role2);
	}

	public void delRoleById(String roleId) throws Exception {
		roleDao.delRoleById(roleId);
		applicationContext.publishEvent(new RoleChangedEvent(this));
	}

	public List<String> queryMenuIdByRoleId(String roleId) {
		List<Role> list = roleDao.findBySql("select r from Role r where r.roleId = ?",roleId);
		List<String> menuIds = new ArrayList<String>();
		if(list != null && !list.isEmpty()) {
			Role r = list.get(0);
			Set<Menu> menus = r.getMenus();
			for (Menu menu : menus) {
				String menuId = menu.getMenuId();
				menuIds.add(menuId);
			}
		}
		return menuIds;
	}
	
	public List<Role> queryAllRoleWithMenu() {
		List<Role> list = roleDao.findBySql("select r from Role r ");
		for (Role role : list) {
			role.getMenus().size();
		}
		return list;
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext)
			throws BeansException {
		this.applicationContext = applicationContext;
	}

	public List<Role> getTopRole() {
		Set<Criterion> set = new HashSet<Criterion>();
		set.add(Restrictions.eq("parentId","0"));
						
		Set<Order> orderSet = new HashSet<Order>();
		orderSet.add(Order.asc("roleId"));
		
		List<Role> result = roleDao.query(set,orderSet);
		return result;
	}

	public List<Role> getSubRoles(String id) {
		Set<Criterion> set = new HashSet<Criterion>();
		set.add(Restrictions.eq("parentId",id));
						
		Set<Order> orderSet = new HashSet<Order>();
		orderSet.add(Order.asc("roleId"));
		
		List<Role> result = roleDao.query(set,orderSet);
		return result;
	}
}
